home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Presentations / Presentations ’93 / Macintosh as Internet Server ƒ / inetd / UDP.cp < prev    next >
Text File  |  1993-04-27  |  5KB  |  259 lines

  1.  
  2. #include "UDP.h"
  3. #include "InetD.h"
  4.  
  5. #include <UFailure.h>
  6. #include <myUtils.h>
  7.  
  8. #include <Resources.h>
  9. #include <Devices.h>
  10. #include <Processes.h>
  11. #include <Desk.h>
  12.  
  13. UDPListener::UDPListener(InetD* daemon)
  14. {
  15.     fDaemon        = daemon;
  16. }
  17.  
  18. UDPListener::~UDPListener()
  19. {
  20.     this->Release();
  21. }
  22.  
  23. Boolean
  24. UDPListener::Initialize()
  25. {
  26.     int            numPBs;
  27.     int            i;
  28.     
  29.     Handle        resHandle;
  30.     short        theID;
  31.     ResType        theType;
  32.     Str255        theName;
  33.     
  34.     numPBs = CountResources('UDP ');
  35.     if (numPBs > 0) {
  36.         for (i = 1; i <= numPBs; i++) {
  37.             resHandle = GetIndResource('UDP ', i);
  38.             FailResError();
  39.             
  40.             GetResInfo(resHandle, &theID, &theType, theName);
  41.             this->ListenOn((udp_port) theID);
  42.             
  43.             ReleaseResource(resHandle);
  44.         }
  45.         
  46.         return true;
  47.     }
  48.     else
  49.         return false;
  50. }
  51.  
  52. void
  53. UDPListener::DoNull()
  54. {
  55.     PortItem*    item;
  56.     Handle        resHandle;
  57.     FailInfo    fi;
  58.     
  59.     while ((item = (PortItem*) fLaunchList.First()) != nil) {
  60.         resHandle = GetResource('UDP ', item->fPort);
  61.         FailResError();
  62.         
  63.         HLock(resHandle);
  64.         
  65.         fDaemon->LogIt(false, "Attempting to launch %P\n", ((FSSpec*) *resHandle)->name);
  66.  
  67.         if (fi.Try()) {
  68.             fDaemon->Launch(item->fStream, (FSSpec*) *resHandle, 'USTR', &item->fPSN);
  69.             fi.Success();
  70.         }
  71.         else {
  72.             this->CloseDown(item->fStream);
  73.             fDaemon->LogIt(true, "InetD:\n\nFailed to launch %P for UDP port %d",
  74.                                     ((FSSpec*) *resHandle)->name, item->fPort);
  75.         }
  76.  
  77.         fLaunchList.TakeOff(item);
  78.         fRestartList.PutOn(item);
  79.         
  80.         HUnlock(resHandle);
  81.         ReleaseResource(resHandle);
  82.     }
  83. }
  84.  
  85. void
  86. UDPListener::ListenOn(udp_port thePort)
  87. {
  88.     UDPiopb        pb;
  89.     Ptr            rcvPtr    = nil;
  90.     PortItem*    nu;
  91.     
  92.     rcvPtr = NewPtrSys(4 * 1024);
  93.     FailMemError();
  94.     
  95.     pb.ioCompletion = nil;
  96.     pb.csCode = UDPCreate;
  97.     pb.ioCRefNum = fDaemon->GetDriver();
  98.     pb.csParam.create.rcvBuff = rcvPtr;
  99.     pb.csParam.create.rcvBuffLen = 4 * 1024;
  100.     pb.csParam.create.localPort = thePort;
  101.     pb.csParam.create.notifyProc = &UDPNotify;
  102.     pb.csParam.create.userDataPtr = (Ptr) this;
  103.     
  104.     FailOSErr(PBControlSync((ParmBlkPtr) &pb));
  105.  
  106.     nu = new PortItem;
  107.     FailNIL(nu);
  108.     
  109.     nu->fStream = pb.udpStream;
  110.     nu->fPort = pb.csParam.create.localPort;
  111.     nu->fDaemon = fDaemon;
  112.     
  113.     fWaitList.PutOn(nu);
  114. }
  115.  
  116. void
  117. UDPListener::CloseDown(StreamPtr stream)
  118. {
  119.     UDPiopb    pb;
  120.  
  121.     pb.csCode = UDPRelease;
  122.     pb.ioCRefNum = fDaemon->GetDriver();
  123.     pb.udpStream = stream;
  124.     
  125.     FailOSErr(PBControlSync((ParmBlkPtr) &pb));
  126.     
  127.     DisposePtr(pb.csParam.create.rcvBuff);
  128.     FailMemError();
  129. }
  130.  
  131. void
  132. UDPListener::Release()
  133. {
  134.     PortItem*    item;
  135.     
  136.     while ((item = (PortItem*) fWaitList.First()) != nil) {
  137.         this->CloseDown(item->fStream);
  138.         fWaitList.TakeOff(item);
  139.         delete item;
  140.     }
  141.         
  142.     while ((item = (PortItem*) fLaunchList.First()) != nil) {
  143.         this->CloseDown(item->fStream);
  144.         fLaunchList.TakeOff(item);
  145.         delete item;
  146.     }
  147. }
  148.  
  149. void
  150. UDPListener::NotifyMe(PSNPtr psn, StreamPtr stream, ProcPtr proc, Ptr usr)
  151. {
  152.     PortItem*    nu = new PortItem;
  153.     FailNIL(nu);
  154.  
  155.     nu->fPSN.highLongOfPSN    = psn->highLongOfPSN;
  156.     nu->fPSN.lowLongOfPSN    = psn->lowLongOfPSN;
  157.     nu->fStream                = stream;
  158.     nu->fProc                = proc;
  159.     nu->fUsrPtr                = usr;
  160.     
  161.     fNoteeList.PutOn(nu);
  162. }
  163.  
  164. /*    These currently gets called with the PSN of every app that
  165.     we launch, even the ones that don't request ASR service,
  166.     hence its okay if the notee isn't found.
  167. */
  168. void
  169. UDPListener::UnNotify(PSNPtr psn)
  170. {
  171.     PortItem*    old;
  172.  
  173.     old = fNoteeList.GetItem(psn);
  174.     if (old) {
  175.         fNoteeList.TakeOff(old);
  176.         delete old;
  177.     }
  178. }
  179.  
  180. void
  181. UDPListener::ListenAgain(PSNPtr psn)
  182. {
  183.     PortItem*    old;
  184.     udp_port    port;
  185.  
  186.     old = fRestartList.GetItem(psn);
  187.     if (old) {
  188.         fRestartList.TakeOff(old);
  189.         port = old->fPort;
  190.         delete old;
  191.         
  192.         this->ListenOn(port);
  193.     }
  194. }
  195.  
  196. PortItem::PortItem()
  197. {
  198.     fPort = 0;
  199.  
  200.     fStream = nil;
  201.     fProc = nil;
  202.     fUsrPtr = nil;
  203.     fPSN.highLongOfPSN = 0;
  204.     fPSN.lowLongOfPSN = 0;
  205.     
  206.     fDaemon = nil;
  207. }
  208.  
  209. PortItem*
  210. UPortList::GetItem(PSNPtr psn)
  211. {
  212.     PortItem*    it = (PortItem*) this->First();
  213.     
  214.     while (it && (!SameProcesses(psn, &it->fPSN)))
  215.         it = (PortItem*) it->fNext;
  216.         
  217.     return it;
  218. }
  219.  
  220. PortItem*
  221. UPortList::GetItem(StreamPtr stream)
  222. {
  223.     PortItem*    it = (PortItem*) this->First();
  224.     
  225.     while (it && (stream != it->fStream))
  226.         it = (PortItem*) it->fNext;
  227.         
  228.     return it;
  229. }
  230.  
  231. pascal void    
  232. UDPNotify(    StreamPtr stream,
  233.             unsigned short eventCode,
  234.             Ptr    usrData,
  235.             struct ICMPReport* icmp)
  236. {
  237.     PortItem*        them;
  238.     UDPListener*    udp = (UDPListener*) usrData;
  239.     
  240.     if (eventCode == UDPDataArrival) {
  241.         them = udp->fWaitList.GetItem(stream);
  242.         if (them) {
  243.             udp->fWaitList.TakeOff(them);
  244.             udp->fLaunchList.PutOn(them);
  245.             WakeUpProcess(&them->fDaemon->fPSN);
  246.             return;
  247.         }
  248.     }
  249.     
  250.     /*    if we get here, the event wasn't for a connection
  251.         i'm mantaining, therefore it needs to be passed
  252.         on to whoever is.
  253.     */
  254.     them = udp->fNoteeList.GetItem(stream);
  255.     if (them && them->fProc) 
  256.         (*(UDPNotifyProc) them->fProc)(stream, eventCode, them->fUsrPtr, icmp);
  257. }
  258.  
  259.